#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>

#include "sample_comm.h"

#include "od_def.h"
#include "od_trace.h"
#include "od_task.h"
#include "od_tube.h"
#include "od_os.h"
#include "od_msg.h"
#include "od_os_config.h"
#include "od_engine.h"
#include "HisiDecVpssOutDynamicSet.h"

#define HiMPP_TSK_STACK_SIZE    (4*1024 * 1024)   /*线程栈资源大小*/

#define HIOUT_ASSERT_RETURN(expr,retval)    \
        do { \
        if (!(expr)) { assert(expr); return retval; } \
        } while (0)


typedef struct
{
    TASK_COMMON_MEMBERS
        
    int *chnCfgDone;
    struct //HiMPP-API core parameter config!
    {
        VO_LAYER VoLayer;
    }himpp;
        
    HiMPP_dynamic_params params_inside;
}HiMPP_obj;


params_def HiMPP_dynamic_params_def[]=
{
    {OFFSET(HiMPP_dynamic_params, voMode),   PT_VAR_INT32 | PT_START_STOP , sizeof(int), VO_MODE_1MUX, VO_MODE_9MUX},     
    {0, 0, 0, 0, 0}
};

const HiMPP_static_params glb_HiMPP_static_params_default = 
{
    "HiMPP-set"
};

const HiMPP_dynamic_params glb_HiMPP_dynamic_params_default = 
{
    VO_MODE_9MUX,        /*voMode*/
};

HI_S32 HiMPP_get_wndnum(SAMPLE_VO_MODE_E enMode)
{
    HI_U32 u32WndNum = 0;
    
    switch (enMode)
    {
        case VO_MODE_1MUX:
            u32WndNum = 1;
            break;

        case VO_MODE_2MUX:
            u32WndNum = 2;
            break;
        
        case VO_MODE_4MUX:
            u32WndNum = 4;
            break;
        
        case VO_MODE_8MUX:
            u32WndNum = 8;
            break;
        
        case VO_MODE_9MUX:
            u32WndNum = 9;
            break;
        
        case VO_MODE_16MUX:
            u32WndNum = 16;
            break;            
        
        default:
            RPTERR("unknown enMode <%d>!\n", enMode);
            return 9;
    }
    
    return u32WndNum;
}


static int HiMPP_start_stop(HiMPP_obj *obj)
{
    HiMPP_dynamic_params *param = obj->params;
    HiMPP_dynamic_params *params_inside = &obj->params_inside;
    HI_S32 s32Ret, i;
    HI_U32 u32WndNum;

    /*wait until HisDecVpssOut start!!*/
    while( *obj->chnCfgDone == OD_FALSE ) {
        RPTDBG("block here!!");
        od_msleep(200);
    }

    obj->himpp.VoLayer = SAMPLE_VO_LAYER_VHD0;

    if (params_inside->voMode != param->voMode) {
        s32Ret = SAMPLE_COMM_VO_StartChn(obj->himpp.VoLayer, param->voMode);
        if(s32Ret != HI_SUCCESS)
        {		
            RPTERR("vdec bind vpss fail for %#x!\n", s32Ret);
            goto END4_4;
        }

        u32WndNum = HiMPP_get_wndnum(param->voMode);
        for (i = 0; i < u32WndNum; i++) {
            s32Ret = HI_MPI_VDEC_StartRecvStream(i);
            if (s32Ret != HI_SUCCESS) {
                RPTERR("HI_MPI_VDEC_StartRecvStream(%d) start error!", i);
            }
        }
    }

    return OD_OK;

END4_4:    
    SAMPLE_COMM_VO_StopChn(obj->himpp.VoLayer, param->voMode);  

    return OD_ERROR;
}

static void HiMPP_start_stop_delete(HiMPP_obj *obj)
{   
    HiMPP_dynamic_params *param_inside = &obj->params_inside;
    HiMPP_dynamic_params *param = obj->params;
    HI_S32 s32Ret, u32WndNum, i;

    if (param_inside->voMode != param->voMode) {
        s32Ret = SAMPLE_COMM_VO_StopChn(obj->himpp.VoLayer, param_inside->voMode);
        if(s32Ret != HI_SUCCESS)
        {		
            RPTERR("SAMPLE_COMM_VO_StopChn for %#x!\n", s32Ret);
            return;
        }

        u32WndNum = HiMPP_get_wndnum(param_inside->voMode);
        for (i = 0; i < u32WndNum; i++) {
            s32Ret = HI_MPI_VDEC_StopRecvStream(i);
            if (s32Ret != HI_SUCCESS) {
                RPTERR("HI_MPI_VDEC_StartRecvStream(%d) start error!", i);
            }
        }
    }
}


static int HiMPP_ret_set(HiMPP_obj *obj)
{
    HiMPP_dynamic_params *param = obj->params;

    memcpy(&obj->params_inside, param, sizeof(HiMPP_dynamic_params));
    return OD_OK;
}

static int HiMPP_process(HiMPP_obj *obj)
{
    RPTDBG("run loop!");
    od_msleep(500);
    return OD_OK;
}

HiMPP_handle HiMPP_create(HiMPP_static_params *static_params,
                           HiMPP_dynamic_params *dynamic_params)
{
    HiMPP_obj *obj = NULL;
    HiMPP_dynamic_params *params = NULL;

    HIOUT_ASSERT_RETURN(static_params, NULL);

    obj = od_task_create((char *)static_params->task_name, sizeof(HiMPP_obj));
    HIOUT_ASSERT_RETURN(obj, NULL);

    obj->tab = HiMPP_dynamic_params_def;
    obj->params_nums = sizeof(HiMPP_dynamic_params_def) / sizeof(params_def) - 1;

    params = od_calloc(1, sizeof(HiMPP_dynamic_params));
    HIOUT_ASSERT_RETURN(params, NULL);

    if (NULL == dynamic_params)
        memcpy(params, &glb_HiMPP_dynamic_params_default, sizeof(HiMPP_dynamic_params));
    else
        memcpy(params, dynamic_params, sizeof(HiMPP_dynamic_params));

    HIOUT_ASSERT_RETURN(static_params->config_done, NULL);
    obj->chnCfgDone = static_params->config_done;

    obj->params = (void *)params;
    obj->stack_size = HiMPP_TSK_STACK_SIZE;
    obj->pf_start_stop  = (void *)HiMPP_start_stop;
    obj->pf_malloc_free = NULL;
    obj->pf_rt_set = (void *)HiMPP_ret_set;
    obj->pf_process     = (void *)HiMPP_process;
    obj->pf_malloc_free_delete = NULL;
    obj->pf_start_stop_delete = (void *)HiMPP_start_stop_delete;
    
    RPTDBG("create success!");
    return (HiMPP_handle)obj;
}

/*_*/

